home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Main.bin / SimpleTextBoundary.java < prev    next >
Text File  |  1998-09-22  |  10KB  |  307 lines

  1. /*
  2.  * @(#)SimpleTextBoundary.java    1.15 98/02/12
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. package java.text;
  32.  
  33. /**
  34.  * SimpleTextBoundary is an implementation of the BreakIterator
  35.  * protocol.  SimpleTextBoundary uses a state machine to compute breaks.
  36.  * There are currently several subclasses of SimpleTextBoundary that
  37.  * compute breaks for sentences, words, lines, and characters.  They are
  38.  * accessable through static functions of SimpleTextBoundary.
  39.  * @see BreakIterator
  40.  */
  41.  
  42. final class SimpleTextBoundary extends BreakIterator
  43. {
  44.  
  45.     private int pos;
  46.     private CharacterIterator text;
  47.     private TextBoundaryData data;
  48.  
  49.     // internally, the not-a-Unicode value is used as a sentinel value meaning
  50.     // "the end of the string" for the purposes of looking up an appropriate
  51.     // state transition when you've run off the end of the string
  52.     private static final char END_OF_STRING = '\uffff';
  53.  
  54.     /**
  55.      * Create a SimpleTextBoundary using the specified tables. Currently,
  56.      * the table format is private.
  57.      * @param data data used for boundary determination
  58.      */
  59.     protected SimpleTextBoundary(TextBoundaryData data)
  60.     {
  61.         this.data = data;
  62.         text = new StringCharacterIterator("");
  63.         pos = text.getBeginIndex();
  64.     }
  65.  
  66.     /**
  67.      * Compares the equality of two SimpleTextBoundary objects.
  68.      * @param obj the SimpleTextBoundary object to be compared with.
  69.      * @return true if the given obj is the same as this
  70.      * SimpleTextBoundary object; false otherwise.
  71.      */
  72.     public boolean equals(Object obj)
  73.     {
  74.         if (this == obj)
  75.             return true;
  76.         if (!(obj instanceof SimpleTextBoundary))
  77.             return false;
  78.  
  79.         SimpleTextBoundary that = (SimpleTextBoundary) obj;
  80.  
  81.         // The data classes are final and sharable. Only the
  82.         // class type needs to be compared.
  83.         if (this.data.getClass() != that.data.getClass())
  84.             return false;
  85.         if (this.hashCode() != that.hashCode())
  86.             return false;
  87.         if (pos != that.pos)
  88.             return false;
  89.         if (!text.equals(that.text))
  90.             return false;
  91.         return true;
  92.     }
  93.  
  94.     /**
  95.      * Compute a hashcode for this enumeration
  96.      * @return A hash code
  97.      */
  98.     public int hashCode()
  99.     {
  100.         return getClass().hashCode() ^ text.hashCode();
  101.     }
  102.  
  103.     /**
  104.      * Overrides Cloneable
  105.      */
  106.     public Object clone()
  107.     {
  108.         try {
  109.             SimpleTextBoundary other = (SimpleTextBoundary) super.clone();
  110.             other.text = (CharacterIterator) text.clone();
  111.             // The data classes are final and sharable.
  112.             // They don't need to be cloned.
  113.             return other;
  114.         } catch (InternalError e) {
  115.             throw new InternalError();
  116.         }
  117.     }
  118.  
  119.     /**
  120.      * Get the text being scanned by the enumeration
  121.      * @return the text being scanned by the enumeration
  122.      */
  123.     public CharacterIterator getText()
  124.     {
  125.         return text;
  126.     }
  127.  
  128.     /**
  129.      * Set a new text string for enumeration.  The position of the
  130.      * enumerator is reset to first().
  131.      * @param newText new text to scan.
  132.      */
  133.     public void setText(String newText)
  134.     {
  135.         text = new StringCharacterIterator(newText);
  136.         pos = text.getBeginIndex();
  137.     }
  138.  
  139.     /**
  140.      * Set a new text to scan.  The position is reset to first().
  141.      * @param newText new text to scan.
  142.      */
  143.     public void setText(CharacterIterator newText)
  144.     {
  145.         text = newText;
  146.         pos = text.getBeginIndex();
  147.     }
  148.  
  149.     /**
  150.      * Return the first boundary. The iterator's current position is set
  151.      * to the first boundary.
  152.      */
  153.     public int first()
  154.     {
  155.         pos = text.getBeginIndex();
  156.         return pos;
  157.     }
  158.  
  159.     /**
  160.      * Return the last boundary. The iterator's current position is set
  161.      * to the last boundary.
  162.      */
  163.     public int last()
  164.     {
  165.         pos = text.getEndIndex();
  166.         return pos;
  167.     }
  168.  
  169.     /**
  170.      * Return the nth boundary from the current boundary
  171.      * @param index which boundary to return.  A value of 0
  172.      * does nothing.
  173.      * @return the nth boundary from the current position.
  174.      */
  175.     public int next(int increment)
  176.     {
  177.         int result = current();
  178.         if (increment < 0) {
  179.             for (int i = increment; (i < 0) && (result != DONE); ++i) {
  180.                 result = previous();
  181.             }
  182.         }
  183.         else {
  184.             for(int i = increment; (i > 0) && (result != DONE); --i) {
  185.                 result = next();
  186.             }
  187.         }
  188.         return result;
  189.     }
  190.  
  191.     /**
  192.      * Return the boundary preceding the last boundary
  193.      */
  194.     public int previous()
  195.     {
  196.         if (pos > text.getBeginIndex()) {
  197.             int startBoundary = pos;
  198.             pos = previousSafePosition(pos-1);
  199.             int prev = pos;
  200.             int next = next();
  201.             while (next < startBoundary && next != DONE) {
  202.                 prev = next;
  203.                 next = next();
  204.             }
  205.             pos = prev;
  206.             return pos;
  207.         }
  208.         else {
  209.             return DONE;
  210.         }
  211.     }
  212.  
  213.     /**
  214.      * Return the next text boundary
  215.      * @return the character offset of the text boundary or DONE if all
  216.      * boundaries have been returned.
  217.      */
  218.     public int next()
  219.     {
  220.         int result = pos;
  221.         if (pos < text.getEndIndex()) {
  222.             pos = nextPosition(pos);
  223.             result = pos;
  224.         }
  225.         else {
  226.             result = DONE;
  227.         }
  228.         return result;
  229.     }
  230.  
  231.     /**
  232.      * Return the first boundary after the specified offset
  233.      * @param offset the offset to start
  234.      * @return int the first boundary after offset
  235.      */
  236.     public int following(int offset)
  237.     {
  238.         if (offset < text.getBeginIndex() || offset >= text.getEndIndex())
  239.             throw new IllegalArgumentException(
  240.               "nextBoundaryAt offset out of bounds");
  241.         pos = previousSafePosition(offset);
  242.         int result;
  243.         do {
  244.             result = next();
  245.         } while (result <= offset && result != DONE);
  246.         return result;
  247.     }
  248.  
  249.     /**
  250.      * Return the boundary last returned by previous or next
  251.      * @return int the boundary last returned by previous or next
  252.      */
  253.     public int current()
  254.     {
  255.         return pos;
  256.     }
  257.  
  258.     //.................................................
  259.     //utility functions.  These functions don't change the current position.
  260.     private int previousSafePosition(int offset)
  261.     {
  262.         int result = text.getBeginIndex();
  263.         int state = data.backward().initialState();
  264.  
  265.         for (char c = text.setIndex(offset);
  266.              c != CharacterIterator.DONE && !data.backward().isEndState(state);
  267.              c = text.previous()) {
  268.  
  269.             state = data.backward().get(state, mappedChar(c));
  270.             if (data.backward().isMarkState(state)) {
  271.                 result = text.getIndex();
  272.             }
  273.         }
  274.         return result;
  275.     }
  276.  
  277.     private int nextPosition(int offset)
  278.     {
  279.         int getEndIndex = text.getEndIndex();
  280.         int state = data.forward().initialState();
  281.  
  282.         for (char c = text.setIndex(offset);
  283.              c != CharacterIterator.DONE && !data.forward().isEndState(state);
  284.              c = text.next()) {
  285.             state = data.forward().get(state, mappedChar(c));
  286.             if (data.forward().isMarkState(state)) {
  287.                 getEndIndex = text.getIndex();
  288.             }
  289.         }
  290.         if (data.forward().isEndState(state))
  291.             return getEndIndex;
  292.         else {
  293.             state = data.forward().get(state, mappedChar(END_OF_STRING));
  294.             if (data.forward().isMarkState(state))
  295.                 return text.getEndIndex();
  296.             else
  297.                 return getEndIndex;
  298.         }
  299.     }
  300.  
  301.     protected int mappedChar(char c)
  302.     {
  303.         return data.map().mappedChar(c);
  304.     }
  305.  
  306. }
  307.